from django import forms
from django.forms import Form
from web import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django.conf import settings
import random
from utils.tencent.sms import send_sms_single
from django_redis import get_redis_connection
from web import models
from utils import encrypt


# 构造注册表单
class RegisterModelForm(forms.ModelForm):
    mobile_phone = forms.CharField(label='手机号',
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])  # 正则表达式,报错信息
    password = forms.CharField(label='密码', widget=forms.PasswordInput(), min_length=8, max_length=64,
                               error_messages={'max_length': '密码长度不能大于64个字符',
                                               'min_length': '密码长度不能小于8个字符'})  # 使用插件
    confirm_password = forms.CharField(label='重复密码', widget=forms.PasswordInput(), min_length=8, max_length=64,
                                       error_messages={'max_length': '重复密码长度不能大于64个字符',
                                                       'min_length': '重复密码长度不能小于8个字符'})  # 使用插件
    code = forms.CharField(label='验证码')

    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone', 'code']  # 可以自己规定显示顺序

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():  # 可以拿到上面的所有字段
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = '请输入{}'.format(field.label)

    # 定义用户名不重复钩子
    def clean_username(self):
        username = self.cleaned_data['username']
        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户名已存在')
        return username

    # 定义邮箱不能重复
    def clean_email(self):
        email = self.cleaned_data['email']
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已存在')
        return email

    # 密码转化为密文
    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密&返回
        return encrypt.md5(pwd)

    # 判断两个密码是否一致
    def clean_confirm_password(self):
        pwd = self.cleaned_data['password']
        confirm_pwd = encrypt.md5(self.cleaned_data['confirm_password'])

        if pwd != confirm_pwd:
            raise ValidationError('两次密码不一致')
        return confirm_pwd

    # 判断手机号是否重复
    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone)
        if exists:
            raise ValidationError('手机号已注册')
        return mobile_phone

    # 验证code校验码
    def clean_code(self):
        code = self.cleaned_data['code']
        # mobile_phone = self.cleaned_data['mobile_phone']  # 若前面出现异常，这个地方将报错，取不到值
        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:  # 若不存在
            raise ValidationError('验证码失效或未发送，请重新发送')

        redis_str_code = redis_code.decode('utf-8')
        if code.strip() != redis_str_code:  # 去除空白
            raise ValidationError('校验码错误请重新发送')

        return code


# 构造手机号校验表单
class SendSmsForm(forms.Form):
    mobile_phone = forms.CharField(required=False, label='手机号',
                                   validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    # 定义__init__添加传进来的参数request
    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        """手机号校验的钩子"""
        mobile_phone = self.cleaned_data['mobile_phone']

        # 判断短信模板是否有问题
        tpl = self.request.GET.get('tpl')
        template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not template_id:
            raise ValidationError('模板错误')

        # 校验数据库中是否已有手机号
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已存在')

        # 发短信 & 写入redis
        # code = random.randrange(1000, 9999)
        # sms = send_sms_single('+86{}'.format(mobile_phone), template_id, [str(code), ])
        # print(sms)
        # if sms['result'] != 0:
        #     raise ValidationError('短信发送失败:{}'.format(sms['errmsg']))

        # 验证码写入redis(django-redis)
        # conn = get_redis_connection()
        # conn.set(mobile_phone, code, ex=60)

        return mobile_phone
